package com.yzl.frelink.service.matlab;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Service;

import com.yzl.frelink.entities.component.Gate;
import com.yzl.frelink.entities.component.Port;
import com.yzl.frelink.entities.model.Line;
import com.yzl.frelink.entities.model.Model;

@Service
public class ModelCompiler {
    public String compileModel(Model model) {
        return compileComponents(model) + "\n" + compileLines(model);
    }

    public String compileComponents(Model model) {
        List<String> inputs = new ArrayList<>();
        List<String> outputs = new ArrayList<>();
        for (Port port : model.getPorts()) {
            if (port.getType().equals("Input")) {
                inputs.add("\"" + port.getName() + "\"");
            } else if (port.getType().equals("Output")) {
                outputs.add("\"" + port.getName() + "\"");
            }
        }

        List<String> gatesName = new ArrayList<>();
        List<String> gatesPort = new ArrayList<>();
        List<String> gatesType = new ArrayList<>();
        for (Gate gate : model.getGates()) {
            gatesName.add("\"" + gate.getName() + "\"");
            gatesPort.add("\"" + String.valueOf(gate.getPortNum()) + "\"");
            gatesType.add("\"" + gate.getType() + "\"");
        }
        StringBuilder sb = new StringBuilder();
        sb.append("inBlocks = [").append(String.join(",", inputs)).append("];\n");
        sb.append("for i=1:").append(inputs.size()).append("\n");
        sb.append("  add_block(\"simulink/Commonly Used Blocks/In1\", myModel+\"/\"+inBlocks(i));\nend\n\n");
        sb.append("outBlocks = [").append(String.join(",", outputs)).append("];\n");
        sb.append("for i=1:").append(outputs.size()).append("\n");
        sb.append("  add_block(\"simulink/Commonly Used Blocks/Out1\", myModel+\"/\"+outBlocks(i));\nend\n\n");
        sb.append("outGatesName = [").append(String.join(",", gatesName)).append("];\n");
        sb.append("outGatesPort = [").append(String.join(",", gatesPort)).append("];\n");
        sb.append("outGatesType = [").append(String.join(",", gatesType)).append("];\n");
        sb.append("for i=1:").append(gatesName.size()).append("\n");
        sb.append("  add_block(\"simulink/Logic and Bit Operations/Logical Operator\", myModel+\"/\"+outGatesName(i));\n");
        sb.append("  set_param(myModel+\"/\"+outGatesName(i),'Operator',outGatesType(i),'Inputs',outGatesPort(i));\nend\n");

        return sb.toString();
//         return """
// inBlocks = [%s];
// for i=1:%d
//   add_block("simulink/Commonly Used Blocks/In1", myModel+"/"+inBlocks(i)); 
// end

// outBlocks = [%s];
// for i=1:%d
//   add_block("simulink/Commonly Used Blocks/Out1", myModel+"/"+outBlocks(i)); 
// end

// outGatesName = [%s];
// outGatesPort = [%s];
// outGatesType = [%s];
// for i=1:%d
//   add_block("simulink/Logic and Bit Operations/Logical Operator", myModel+"/"+outGatesName(i));
//   set_param(myModel+"/"+outGatesName(i),'Operator',outGatesType(i),'Inputs',outGatesPort(i));
// end""".formatted(String.join(",", inputs), inputs.size(), String.join(",", outputs), outputs.size(), String.join(",", gatesName), String.join(",", gatesPort), String.join(",", gatesType), gatesName.size());
    }

    public String compileLines(Model model) {
        List<String> outs = new ArrayList<>();
        List<String> ins = new ArrayList<>();
        for (Line line : model.getLines()) {
            outs.add(line.getSource());
            ins.add(line.getDestination());
        }
        StringBuilder sb = new StringBuilder();
        sb.append("lineOuts = [").append(String.join(",", outs)).append("];\n");
        sb.append("lineIns = [").append(String.join(",", ins)).append("];\n");
        sb.append("for i=1:").append(outs.size()).append("\n");
        sb.append("  add_line(myModel, lineOuts(i), lineIns(i));\n");
        sb.append("end\n");
        return sb.toString();
//         return """
// lineOuts = [%s];
// lineIns = [%s];
// for i=1:%d
//   add_line(myModel, lineOuts(i), lineIns(i));
// end
// """.formatted(String.join(",", outs), String.join(",", ins), outs.size());
    }
}
